﻿using Abp.Application.Services.Dto;
using Abp.Dependency;
using Abp.Runtime.Caching;
using Abp.Runtime.Security;
using HCD.Web.MDC.Startup;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Configuration;
using System;
using System.Linq;
using System.Reflection;
using System.Security.Claims;
using System.Threading;

namespace HCD.Web.MDC.Authorizer
{
    /// <summary>
    ///
    /// </summary>
    public class AuthorFilter : IAuthorizationFilter, ITransientDependency
    {
        private readonly ICacheManager _cacheManager;
        private readonly IConfiguration _configuration;

        /// <summary>
        ///
        /// </summary>
        /// <param name="CacheManager"></param>
        /// <param name="Configuration"></param>
        public AuthorFilter(ICacheManager CacheManager, IConfiguration Configuration)
        {
            _cacheManager = CacheManager;
            _configuration = Configuration;
        }

        /// <summary>
        /// 验证
        /// </summary>
        /// <param name="context"></param>
        public void OnAuthorization(AuthorizationFilterContext context)
        {
            //匿名访问特性
            var act = (context.ActionDescriptor as ControllerActionDescriptor).MethodInfo.CustomAttributes.Where(a => a.AttributeType == typeof(AllowAnonymousAttribute));
            var ctrl = (context.ActionDescriptor as ControllerActionDescriptor).MethodInfo.ReflectedType.CustomAttributes.Where(a => a.AttributeType == typeof(AllowAnonymousAttribute));

            if (act.Any() || ctrl.Any())//是否 不需要验证登录
            {
                return;
            }
            //验证token
            var token = GetToken(context);
            var auth = new AuthModel();
            try
            {
                auth = JWTUtil.DecodeToken(token);
                if (auth.Exp < DateTime.Now)
                    throw new Exception("超时");

                context.RouteData.Values.Add("auth", auth);
                if (auth.TenantID.HasValue)
                {
                    var tenant = new Claim(AbpClaimTypes.TenantId, auth.TenantID.ToString());
                    var identity = new ClaimsIdentity();
                    identity.AddClaim(tenant);
                    var principal = new ClaimsPrincipal(identity);
                    Thread.CurrentPrincipal = principal;
                    context.HttpContext.User.AddIdentity(identity);
                }
            }
            catch
            {
                TokenError(context);
                return;
            }

            //如需验证更细致的权限，再扩展
            //PermissionError(context);
            //var ac = (context.ActionDescriptor as ControllerActionDescriptor).MethodInfo.CustomAttributes.Where(at => at.AttributeType == typeof(PermissionAttribute));
            //var co = (context.ActionDescriptor as ControllerActionDescriptor).MethodInfo.ReflectedType.CustomAttributes.Where(at => at.AttributeType == typeof(PermissionAttribute));
            ////需要验证权限
            //if (ac.Any() || co.Any())
            //{

            //}
        }

        private string GetToken(AuthorizationFilterContext context)
        {
            if (!context.HttpContext.Request.Cookies.TryGetValue("ck_token", out string token))
            {
                token = context.HttpContext.Request.Headers["token"];
            }
            return token;
        }

        private void TokenError(AuthorizationFilterContext context)
        {
            //是否为api接口
            var isApi = (context.ActionDescriptor as ControllerActionDescriptor).MethodInfo.ReflectedType.IsDefined(typeof(ApiControllerAttribute), true);
            //是否为ajax请求
            var isAjax = context.HttpContext.Request.Headers["x-requested-with"].Equals("XMLHttpRequest");
            if (isApi || isAjax)
            {
                context.HttpContext.Response.StatusCode = 401;
                context.Result = new JsonResult(new { Success = false, Message = "身份验证错误" });//new UnauthorizedResult();
            }
            else//页面请求重定向
            {
                //租户
                context.Result = new RedirectResult("/Home/Error");
            }
        }

        private void PermissionError(AuthorizationFilterContext context)
        {
            context.HttpContext.Response.StatusCode = 403;
            context.Result = new JsonResult(new { Success = false, Message = "没有权限" });
            return;
        }
    }
}
